//==============================================================================
//	 AdjacencyListGraph2.hh
//
//------------------------------------------------------------------------------
// $Id:$
//------------------------------------------------------------------------------
// $Log:$
//==============================================================================
//.......1.........2.........3.........4.........5.........6.........7.........8
//

#ifndef _SPARSE_GRAPH2
#define _SPARSE_GRAPH2

#include "LocalSTL.hh"
#include "Table.hh"
#include "CLibraryAdditions.hh"




//------------------------------------------------------------------------------
// * AdjacencyListGraph2Edge
//------------------------------------------------------------------------------
// An edge in an adjacency list graph.  
//
class AdjacencyListGraph2Edge{
public:
  string mName;
  float  mWeight;

  // Overload < for sort. 
  friend bool operator<(const AdjacencyListGraph2Edge &a,const AdjacencyListGraph2Edge &b){
	 if (b.mWeight < a.mWeight) return true;
	 else return false;
  }
};

typedef hash_map<const string, AdjacencyListGraph2Edge,BasicStringHashF, eqStr> EdgeHash;

//------------------------------------------------------------------------------
// * AdjacencyListGraph2Node
//------------------------------------------------------------------------------
// A node in an adjacency list graph. 
// 
class AdjacencyListGraph2Node{
public:

  string mName;
  EdgeHash mEdges;

  void AddEdge(string Name,float weight){
	 AdjacencyListGraph2Edge E;
	 E.mName = Name;
	 E.mWeight = weight;
    mEdges[Name] = E;
  }

  bool Contains(string Name){
	 EdgeHash::iterator it;
	 it = mEdges.find(Name);
	 if (it != mEdges.end()) return(true);
	 else return(false);
  }

  float GetEdgeWeight(string Name){
	 if(!Contains(Name)){
		return(-1);
	 }else{
		return(mEdges[Name].mWeight);
	 }
  }

  //void SortEdgesByWeight(){
  // sort(mEdges.begin(),mEdges.end());
  //};

  void Print(string &FileName){
	 ofstream outFile;

	 outFile.open(FileName.c_str());
	 if (outFile.fail()) {
		cout<<FileName<<" open failed."<<endl;
		return;
	 }
	 Print(outFile);
	 outFile.close();
  };

  void Print(ostream &fout){
	 fout<<mName<<"\t";
	 EdgeHash::iterator it;
	 for(it = mEdges.begin();it!= mEdges.end();it++){
		fout<<(*it).second.mName<<"\t";
		fout<<(*it).second.mWeight<<"\t";
	 }
	 fout<<endl;
  };
};


typedef hash_map<const string, AdjacencyListGraph2Node,BasicStringHashF, eqStr> NodeHash;

// KJD Doxygen needs something to tell it where to put line breaks
// or something to say that text should be formatted verbatim. 
// actually, since I generally want to preserve line breaks, I'd
// like this to be a global option.  Also, InitFromTable and CopyToTable
// from .cc file is not getting comments.  What gives?

//------------------------------------------------------------------------------
// * AdjacencyListGraph2
//------------------------------------------------------------------------------
// 
// An adjacency list graph is a standard kind of graph suitable for sparse 
// graphs.  The main purpose of this class is to represent graphs that are
// sparse and for which the adjacency matrix representation is too large. 
// For small graphs, GraphTable is adequate and easier to work with.   
// 
// The basic format of an adjacency list graph is: 
//
// vector<AdjacencyListGraph2Node>
//             -->mName
//                vector<AdjacencyListGraph2Edge>
//                             -->mName
//                             -->mWeight
//
//
class AdjacencyListGraph2: public NodeHash{
public:
  
  void AddEdge(string NodeName,string EdgeName,double Weight);

  void Read(string FileName);
  void Add(string FileName);
  void Write(string FileName);
  void ParseLine(string line,AdjacencyListGraph2Node &N);
  bool Contains(string NodeName,string EdgeName);
  void CompareGraphs(AdjacencyListGraph2 &TestGraph,
							long &TP,long &FP, long &MissingEdges, long &TotalTrueEdges,
							double &sensitivity, double &veracity);

 void CompareGraphsWithCutoff(AdjacencyListGraph2 &TestGraph,
							long &TP,long &FP, long &MissingEdges, long &TotalTrueEdges,
							double &sensitivity, double &veracity,int MinOverlap);

  void GetEdgeDiffs(AdjacencyListGraph2 &TestGraph,
						  vector<string> &MissingNodes,vector<string> &MissingEdges,
						  vector<string> &ExtraNodes,vector<string> &ExtraEdges);

  double GetMinEdgeWeight();
  int  RemoveEdges(double MinEdgeWeight);
  void Print(string FileName);
  void Print(ostream &outFile);
};


#endif
